﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace JustTank
{
    public static class CollisionDispatcher
    {
        public static void HandleCollisions(List<MovingObject> movingObjects, List<GameObject> staticObjects)
        {
            HandleMovingWithStaticCollisions(movingObjects, staticObjects);
        }

        private static void HandleMovingWithStaticCollisions(List<MovingObject> movingObjects, List<GameObject> staticObjects)
        {
            foreach (var movingObject in movingObjects)
            {
                if (movingObject is BotBullet)
                {
                    BotBullet botBullet = movingObject as BotBullet;

                    foreach (var movObj in movingObjects)
                    {
                        if (movObj is TankHuman)
                        {
                            TankHuman tank = movObj as TankHuman;
                            if (IsHit(botBullet, tank))
                            {
                                tank.RespondToCollision();
                            }
                        }
                    }

                    foreach (var staticObject in staticObjects)
                    {
                        if (staticObject is IndestructibleBlock)
                        {
                            IndestructibleBlock indestBlock = staticObject as IndestructibleBlock;
                            if (IsHit(botBullet, indestBlock))
                            {
                                botBullet.RespondToCollision();
                            }
                        }
                    }

                    foreach (var movObj in movingObjects)
                    {
                        if (movObj is PlayerBullet)
                        {
                            PlayerBullet playerBullet = movObj as PlayerBullet;
                            if (botBullet.TopLeft.Equals(playerBullet.TopLeft))
                            {
                                botBullet.RespondToCollision();
                                playerBullet.RespondToCollision();
                            }
                        }
                    }
                }

                if (movingObject is PlayerBullet)
                {
                    PlayerBullet playerBullet = movingObject as PlayerBullet;

                    foreach (var movObj in movingObjects)
                    {
                        if (movObj is TankBot)
                        {
                            TankBot tankBot = movObj as TankBot;
                            if (IsHit(playerBullet, tankBot))
                            {
                                tankBot.RespondToCollision();
                            }
                        }
                    }

                    foreach (var staticObject in staticObjects)
                    {
                        if (staticObject is IndestructibleBlock)
                        {
                            IndestructibleBlock indestBlock = staticObject as IndestructibleBlock;
                            if (IsHit(playerBullet, indestBlock))
                            {
                                playerBullet.RespondToCollision();
                            }
                        }
                    }
                }

                if (movingObject is TankHuman)
                {
                    TankHuman tankHuman = movingObject as TankHuman;
                    foreach (var statObj in staticObjects)
                    {
                        if (statObj is IndestructibleBlock)
                        {
                            IndestructibleBlock indestBlock = statObj as IndestructibleBlock;
                            if (tankHuman.Direction == TankDirection.Up && indestBlock.TopLeft.Equals(new MatrixCoords(tankHuman.TopLeft.Row, tankHuman.TopLeft.Col)))
                            {
                                tankHuman.TopLeft = new MatrixCoords(indestBlock.TopLeft.Row + 1, indestBlock.TopLeft.Col);
                            }
                            else if (tankHuman.Direction == TankDirection.Down && indestBlock.TopLeft.Equals(new MatrixCoords(tankHuman.TopLeft.Row + 1, tankHuman.TopLeft.Col)))
                            {
                                tankHuman.TopLeft = new MatrixCoords(indestBlock.TopLeft.Row - 2, indestBlock.TopLeft.Col);
                            }
                            else if (tankHuman.Direction == TankDirection.Left && indestBlock.TopLeft.Equals(new MatrixCoords(tankHuman.TopLeft.Row, tankHuman.TopLeft.Col)))
                            {
                                tankHuman.TopLeft = new MatrixCoords(indestBlock.TopLeft.Row, indestBlock.TopLeft.Col + 1);
                            }
                            else if (tankHuman.Direction == TankDirection.Right && indestBlock.TopLeft.Equals(new MatrixCoords(tankHuman.TopLeft.Row, tankHuman.TopLeft.Col + 1)))
                            {
                                tankHuman.TopLeft = new MatrixCoords(indestBlock.TopLeft.Row, indestBlock.TopLeft.Col - 2);
                            }
                        }
                    }
                }

                    
                //Stop the tankBot to go out the game field
                if (movingObject is TankBot)
                {
                    TankBot tankBot = movingObject as TankBot;
                    foreach (var staticObject in staticObjects)
                    {
                        if (staticObject is IndestructibleBlock)
                        {
                            IndestructibleBlock indestBlock = staticObject as IndestructibleBlock;
                            if (tankBot.GetTankDirection(tankBot.Speed) == TankDirection.Up && HasBlockInFront(tankBot, indestBlock))
                            {
                                if (HasBlockOnLeft(tankBot, indestBlock))
                                {
                                    tankBot.ChangeDirection(1);

                                    tankBot.TopLeft += tankBot.Speed;
                                    //tankBot.TopLeft += new MatrixCoords(1, 0);
                                }
                                else if (HasBlockOnRight(tankBot, indestBlock))
                                {
                                    tankBot.ChangeDirection(-1);
                                    //tankBot.Speed = new MatrixCoords(1, -1);
                                    tankBot.TopLeft += tankBot.Speed;
                                    //tankBot.TopLeft += new MatrixCoords(1, 0);
                                }
                                else
                                {
                                    tankBot.ChangeDirection(1);

                                    tankBot.TopLeft += tankBot.Speed;
                                    //tankBot.TopLeft += new MatrixCoords(1, 0);
                                }

                                tankBot.TopLeft += new MatrixCoords(1, 0);
                            }
                            else if (tankBot.GetTankDirection(tankBot.Speed) == TankDirection.Left && HasBlockOnLeft(tankBot, indestBlock))
                            {
                                if (HasBlockInFront(tankBot, indestBlock))
                                {
                                    tankBot.ChangeDirection(1);
                                    //tankBot.Speed = new MatrixCoords(1, 1);
                                    tankBot.TopLeft += tankBot.Speed;
                                    //tankBot.TopLeft += new MatrixCoords(1, 0);
                                }
                                else if (HasBlockInBack(tankBot, indestBlock))
                                {
                                    tankBot.ChangeDirection(-1);
                                    //tankBot.Speed = new MatrixCoords(-1, 1);
                                    tankBot.TopLeft += tankBot.Speed;
                                    //tankBot.TopLeft += new MatrixCoords(1, 0);
                                }
                                else
                                {
                                    tankBot.ChangeDirection(1);

                                    tankBot.TopLeft += tankBot.Speed;
                                    //tankBot.TopLeft += new MatrixCoords(1, 0);
                                }

                                tankBot.TopLeft += new MatrixCoords(0, 1);                                
                            }
                            else if (tankBot.GetTankDirection(tankBot.Speed) == TankDirection.Right && HasBlockOnRight(tankBot, indestBlock))
                            {
                                if (HasBlockInFront(tankBot, indestBlock))
                                {
                                    tankBot.ChangeDirection(1);
                                    //tankBot.Speed = new MatrixCoords(1, -1);
                                    tankBot.TopLeft += tankBot.Speed;
                                    //tankBot.TopLeft += new MatrixCoords(1, 0);
                                }
                                else if (HasBlockInBack(tankBot, indestBlock))
                                {
                                    tankBot.ChangeDirection(-1);
                                    //tankBot.Speed = new MatrixCoords(1, -1);
                                    tankBot.TopLeft += tankBot.Speed;
                                    //tankBot.TopLeft += new MatrixCoords(1, 0);
                                }
                                else
                                {
                                    tankBot.ChangeDirection(1);

                                    tankBot.TopLeft += tankBot.Speed;
                                    //tankBot.TopLeft += new MatrixCoords(1, 0);
                                }

                                tankBot.TopLeft += new MatrixCoords(0, -1);                               
                            }
                            else if (tankBot.GetTankDirection(tankBot.Speed) == TankDirection.Down && HasBlockInBack(tankBot, indestBlock))
                            {
                                if (HasBlockOnLeft(tankBot, indestBlock))
                                {
                                    tankBot.ChangeDirection(1);
                                    //tankBot.Speed = new MatrixCoords(-1, 1);
                                    tankBot.TopLeft += tankBot.Speed;
                                    //tankBot.TopLeft += new MatrixCoords(1, 0);
                                }
                                else if (HasBlockOnRight(tankBot, indestBlock))
                                {
                                    tankBot.ChangeDirection(-1);
                                    //tankBot.Speed = new MatrixCoords(-1, 1);
                                    tankBot.TopLeft += tankBot.Speed;
                                    //tankBot.TopLeft += new MatrixCoords(1, 0);
                                }
                                else
                                {
                                    tankBot.ChangeDirection(1);

                                    tankBot.TopLeft += tankBot.Speed;
                                    //tankBot.TopLeft += new MatrixCoords(1, 0);
                                }

                                tankBot.TopLeft += new MatrixCoords(-1, 0);                               
                            }
                        }
                    }
                }
            }
        }


        private static bool HasBlockInFront(Tank tank, IndestructibleBlock indestBlock)
        {
            if (indestBlock.TopLeft.Equals(new MatrixCoords(tank.TopLeft.Row - 1, tank.TopLeft.Col))) //|| indestBlock.TopLeft.Equals(new MatrixCoords(tank.TopLeft.Row - 1, tank.TopLeft.Col)))
            {
                return true;
            }
            else
	        {
                return false;
	        }
        }

        private static bool HasBlockInBack(Tank tank, IndestructibleBlock indestBlock)
        {
            if (indestBlock.TopLeft.Equals(new MatrixCoords(tank.TopLeft.Row + 2, tank.TopLeft.Col))) //|| indestBlock.TopLeft.Equals(new MatrixCoords(tank.TopLeft.Row + 2, tank.TopLeft.Col)))
            {
                return true; 
            }
            else
            {
                return false;
            }
        }

        private static bool HasBlockOnLeft(Tank tank, IndestructibleBlock indestBlock)
        {
            if (indestBlock.TopLeft.Equals(new MatrixCoords(tank.TopLeft.Row, tank.TopLeft.Col - 1))) //|| indestBlock.TopLeft.Equals(new MatrixCoords(tank.TopLeft.Row, tank.TopLeft.Col - 1)))
            {
                return true;
            }
            else
            {
                return false;
            }
        }

        private static bool HasBlockOnRight(Tank tank, IndestructibleBlock indestBlock)
        {
            if (indestBlock.TopLeft.Equals(new MatrixCoords(tank.TopLeft.Row, tank.TopLeft.Col + 2))) //|| indestBlock.TopLeft.Equals(new MatrixCoords(tank.TopLeft.Row, tank.TopLeft.Col + 2)))
            {
                return true;
            }
            else
            {
                return false;
            }
        }




        private static bool IsHit(Bullet bullet, GameObject gameObject)
        {
            if (gameObject is TankHuman)
            {
                TankHuman tank = gameObject as TankHuman;
                if ((tank.Direction == TankDirection.Up) && (bullet.TopLeft.Equals(tank.TopLeft) || bullet.TopLeft.Equals(new MatrixCoords(tank.TopLeft.Row + 1, tank.TopLeft.Col))))
                {
                    return true;
                }
                else if ((tank.Direction == TankDirection.Left) && (bullet.TopLeft.Equals(tank.TopLeft) || bullet.TopLeft.Equals(new MatrixCoords(tank.TopLeft.Row, tank.TopLeft.Col + 1))))
                {
                    return true;
                }
                else if ((tank.Direction == TankDirection.Down) && (bullet.TopLeft.Equals(tank.TopLeft) || bullet.TopLeft.Equals(new MatrixCoords(tank.TopLeft.Row + 1, tank.TopLeft.Col))))
                {
                    return true;
                }
                else if ((tank.Direction == TankDirection.Right) && (bullet.TopLeft.Equals(tank.TopLeft) || bullet.TopLeft.Equals(new MatrixCoords(tank.TopLeft.Row, tank.TopLeft.Col + 1))))
                {
                    return true;
                }
                else
                {
                    return false;
                }

            }

            if (gameObject is TankBot)
            {
                TankBot tankBot = gameObject as TankBot;

                if ((tankBot.GetTankDirection(tankBot.Speed) == TankDirection.Up) && (bullet.TopLeft.Equals(tankBot.TopLeft) || bullet.TopLeft.Equals(new MatrixCoords(tankBot.TopLeft.Row + 1, tankBot.TopLeft.Col))))
                {
                    return true;
                }
                else if ((tankBot.GetTankDirection(tankBot.Speed) == TankDirection.Left) && (bullet.TopLeft.Equals(tankBot.TopLeft) || bullet.TopLeft.Equals(new MatrixCoords(tankBot.TopLeft.Row, tankBot.TopLeft.Col + 1))))
                {
                    return true;
                }
                else if ((tankBot.GetTankDirection(tankBot.Speed) == TankDirection.Down) && (bullet.TopLeft.Equals(tankBot.TopLeft) || bullet.TopLeft.Equals(new MatrixCoords(tankBot.TopLeft.Row + 1, tankBot.TopLeft.Col))))
                {
                    return true;
                }
                else if ((tankBot.GetTankDirection(tankBot.Speed) == TankDirection.Right) && (bullet.TopLeft.Equals(tankBot.TopLeft) || bullet.TopLeft.Equals(new MatrixCoords(tankBot.TopLeft.Row, tankBot.TopLeft.Col + 1))))
                {
                    return true;
                }
                else
                {
                    return false;
                }
            }

            if (gameObject is IndestructibleBlock)
            {
                IndestructibleBlock indestBlock = gameObject as IndestructibleBlock;
                if ((bullet.Direction == TankDirection.Left) && (indestBlock.TopLeft.Equals(new MatrixCoords(bullet.TopLeft.Row, bullet.TopLeft.Col - 1)) || indestBlock.TopLeft.Equals(new MatrixCoords(bullet.TopLeft.Row, bullet.TopLeft.Col))))
                {
                    return true;
                }
                else if ((bullet.Direction == TankDirection.Right) && (indestBlock.TopLeft.Equals(new MatrixCoords(bullet.TopLeft.Row, bullet.TopLeft.Col + 1)) || indestBlock.TopLeft.Equals(new MatrixCoords(bullet.TopLeft.Row, bullet.TopLeft.Col))))
                {
                    return true;
                }
                else if ((bullet.Direction == TankDirection.Up) && (indestBlock.TopLeft.Equals(new MatrixCoords(bullet.TopLeft.Row - 1, bullet.TopLeft.Col)) || indestBlock.TopLeft.Equals(new MatrixCoords(bullet.TopLeft.Row, bullet.TopLeft.Col))))
                {
                    return true;
                }
                else if ((bullet.Direction == TankDirection.Down) && (indestBlock.TopLeft.Equals(new MatrixCoords(bullet.TopLeft.Row + 1, bullet.TopLeft.Col)) || indestBlock.TopLeft.Equals(new MatrixCoords(bullet.TopLeft.Row, bullet.TopLeft.Col))))
                {
                    return true;
                }
                else
                {
                    return false;
                }
            }

            return false;
        }
    }
}
